#include "demo_strategy.h"
#include "time_utils.hpp"

using namespace lt;

void demo_strategy::on_init()
{
	subscrib_signal(_signal, this);
	use_custom_chain(true);
	_order_data = static_cast<persist_data*>(get_userdata(sizeof(persist_data)));
}

void demo_strategy::on_ready()
{
	uint32_t trading_day = get_trading_day();
	_coming_to_close = make_datetime(trading_day, "14:58:00");
	if(_order_data->trading_day!=trading_day||true)
	{
		_order_data->trading_day = trading_day;
		for (size_t i = 0; i < ORDER_ESTID_COUNT; i++)
		{
			_order_data->order_estids[i] = INVALID_ESTID;
		}
	}
	else
	{
		for (size_t i = 0; i < ORDER_ESTID_COUNT; i++)
		{
			if(_order_data->order_estids[i] != INVALID_ESTID)
			{
				auto& order = get_order(_order_data->order_estids[i]);
				if (order.est_id != INVALID_ESTID)
				{
					set_cancel_condition(order.est_id, [this,&order](const tick_info& tick)->bool {

						if (tick.time - order.create_time > 100)
						{
							return true;
						}
						if (tick.time > _coming_to_close)
						{
							return true;
						}
						return false;
						});
				}
				else
				{
					_order_data->order_estids[i] = INVALID_ESTID;
				}
			}
		}
	}
}

void demo_strategy::on_update()
{
	
}

void demo_strategy::on_signal(lt::sigid_t sigid, const code_t& code, lt::action_type type)
{
	if (!is_trading_ready())
	{
		LOG_DEBUG("is_trading_ready not ready\n");
		return;
	}
	auto& tick = get_last_tick(code);
	if (tick.invalid() || tick.time > _coming_to_close)
	{
		//LOG_DEBUG("time > _coming_to_close %s %d %d\n", tick.id.get_id(), tick.time, _coming_to_close);
		return;
	}
	LOG_TRACE("on_tick time : %d.%d %s %f \n", tick.time, tick.tick, tick.id.get_id(), tick.price);
	
	
	if (_order_data->order_estids[ARBITRARILY_BUY] == INVALID_ESTID && type == ACT_BULL)
	{
		_order_data->order_estids[ARBITRARILY_BUY] = buy_for_open(tick.id, _open_once, tick.price);
		print_perist_data("ARBITRARILY_LONG", tick.id);
		
	}
	if (_order_data->order_estids[ARBITRARILY_SELL] == INVALID_ESTID && type == ACT_BEAR)
	{
		_order_data->order_estids[ARBITRARILY_SELL] = sell_for_close(tick.id, _open_once, tick.price);
		print_perist_data("ARBITRARILY_SHORT", tick.id);
	}
	
}



void demo_strategy::on_entrust(const order_info& order)
{
	LOG_INFO("emg_2_strategy on_entrust : %llu %s %d %d %f %d/%d\n", order.est_id, order.code,order.direction,order.offset,order.price, order.last_volume,order.total_volume);
	
	for (size_t i = 0; i < ORDER_ESTID_COUNT; i++)
	{
		if(_order_data->order_estids[i] == order.est_id)
		{
			set_cancel_condition(order.est_id, [this,&order](const tick_info& tick)->bool {

				if(tick.time - order.create_time>100)
				{
					return true;
				}
				if (tick.time > _coming_to_close)
				{
					return true;
				}
				return false;
				});
			break;
		}
	}
	auto& tick = get_last_tick(order.code);
	if (tick.invalid() || tick.time > _coming_to_close)
	{
		//LOG_DEBUG("time > _coming_to_close %s %d %d\n", tick.id.get_id(), tick.time, _coming_to_close);
		return;
	}
	
}

void demo_strategy::on_trade(estid_t localid, const code_t& code, offset_type offset, direction_type direction, double_t price, uint32_t volume)
{
	LOG_INFO("emg_2_strategy on_trade : %llu %s %d %d %f %d\n", localid, code, direction, offset, price, volume);
	
	for (size_t i = 0; i < ORDER_ESTID_COUNT; i++)
	{
		if (_order_data->order_estids[i] == localid)
		{
			_order_data->order_estids[i] = INVALID_ESTID;
			break;
		}
	}
	print_perist_data("on_trade", code);
}

void demo_strategy::on_cancel(estid_t localid, const code_t& code, offset_type offset, direction_type direction, double_t price, uint32_t cancel_volume,uint32_t total_volume)
{
	LOG_INFO("emg_2_strategy on_cancel : %llu %s %d %d %f %d\n", localid, code, direction, offset, price, cancel_volume);
	for (size_t i = 0; i < ORDER_ESTID_COUNT; i++)
	{
		if (_order_data->order_estids[i] == localid)
		{
			_order_data->order_estids[i] = INVALID_ESTID;
			break;
		}
	}
	print_perist_data("on_cancel", code);
}

void demo_strategy::on_error(error_type type, estid_t localid, const uint32_t error)
{
	LOG_ERROR("emg_2_strategy on_error : %llu %d \n", localid, error);
	if(type != ET_PLACE_ORDER)
	{
		return ;
	}
	for (size_t i = 0; i < ORDER_ESTID_COUNT; i++)
	{
		if (_order_data->order_estids[i] == localid)
		{
			_order_data->order_estids[i] = INVALID_ESTID;
			break;
		}
	}
	print_perist_data("on_error", default_code);
}
void demo_strategy::on_destory()
{
	unsubscrib_signal(_signal, this);
}
